
// * - Chat ServerApp for PCMod - * \\
// * Purpose: Provide a chat room for users * \\
// * Client: GChat Program * \\
// * Ports: INT18(SV), EXT17(CL) * \\

APP.Name = "Chat Host" -- Nice Name
APP.AppName = "chat" -- Internal Name

// --- Mandatory Functions --- \\

function APP:Useable()
	// Can the ServerApp be used on this server?
	return true;
end

function APP:Initialize()
	// Server first spawned
	
end
APP.Init = APP.Initialize -- For ease of use

function APP:StartUp()
	// Server turned ON
	if (!self.Server) then return end -- No server = no app
	
	self.Server:OpenPort( 18, "sapp" ) -- Open chat port, redirect traffic to us
	self.Server.Data[ self.Server:EntIndex() ].ConPCs = {} -- Refresh connected PC list
	
end

function APP:ShutDown()
	// Server turned OFF
	if (!self.Server) then return end -- No Server = no app
	
	self:SendToAll( "Server shutting down!" )
	
	self.Server:ClosePort( 18 ) -- Close up chat port
	self.Server.Data[ self.Server:EntIndex() ].ConPCs = {} -- Clear out all connected PCs
end

function APP:PacketRecieved( packet )
	// Packet has arrived for us, on a port opened by us
	local pck = self:DecodePacket( packet )
	if (pck.Port == 18) then
		if (pck.Body[1] == "chat_register") then self:PCConnected( pck.SourceIP ) end
		if (pck.Body[1] == "chat_unregister") then self:PCDisconnected( pck.SourceIP ) end
		if (pck.Body[1] == "chat_message") then self:SendToAll( pck.SourceIP .. ": " .. pck.Body[2] ) end
	end
end

function APP:KillHost()
	self:ShutDown() -- Make sure we shut down properly
end


// --- Non Required Functions --- \\ (But still needed by this app)

function APP:DecodePacket( packet )
	local tmp = {}
		tmp.SourceIP = packet[1]
		tmp.DestIP = packet[2]
		tmp.Port = tonumber( packet[3] )
		tmp.Body = packet[4]
	return tmp
end

function APP:PCConnected( ip )
	local conpcs = self.Server.Data[ self.Server:EntIndex() ].ConPCs
		for _, v in pairs( conpcs ) do
			if (v == ip) then return end -- PC already connected (send back a packet saying 'already connected'?)
		end
		table.insert( conpcs, ip )
	self.Server.Data[ self.Server:EntIndex() ].ConPCs = conpcs
	self:SendChatMessage( ip, "[Connection Successful]" )
	self:SendToAll( ip .. " has connected!" )
end

function APP:PCDisconnected( ip )
	local conpcs = self.Server.Data[ self.Server:EntIndex() ].ConPCs
		local id = 0
		for k, v in pairs( conpcs ) do
			if (v == ip) then
				id = k
			end
		end
		table.remove( conpcs, id )
	self.Server.Data[ self.Server:EntIndex() ].ConPCs = conpcs
	self:SendToAll( ip .. " has disconnected!" )
end

function APP:SendChatMessage( ip, msg )
	local p = { self.Server.Data[self.Server:EntIndex()].IP, ip, 17, { "chat", msg } }
	local result = self.Server:SendPacket( p )
end

function APP:SendToAll( msg )
	local conpcs = self.Server.Data[ self.Server:EntIndex() ].ConPCs
	for k, v in pairs( conpcs ) do
		self:SendChatMessage( v, msg )
	end
end